/*----------------------------------------------------------------------------
Owner(s): Shane Whitfield
$Copyright: $
$Id: $
----------------------------------------------------------------------------*/

#include "go_path.h"
#include "render.h"

/*--------------------------------------------------------------------------*/
const CTexture* CGoPath::m_connectionTexture = NULL;
CGoPath::CGoPath()
{	
	m_length = 0.0f;
	
	//load up the connection texture if it's not already loaded
	if (!m_connectionTexture)
	{
		m_connectionTexture = g_texturemgr.CreateTexture("supplyline_segment.png");
	}
}

void CGoPath::AddPathPoint(const Vector2f& i_pos)
{
	m_travelPoints.push_back(i_pos);
	
	//calc the new length
	int travelpointCount = m_travelPoints.size();
	if (travelpointCount >= 2)
	{
		m_length += Dist(m_travelPoints[travelpointCount - 2], m_travelPoints[travelpointCount - 1]);
		m_distances.push_back(m_length);
	}	
}

void CGoPath::Render()
{
	if (m_travelPoints.size() < 2)
		return;
		
	//render out all the points
	for(int itravelPoint = 0; itravelPoint < m_travelPoints.size() - 1; ++itravelPoint)
	{
		//render a line between me and the connecting node
		g_texturemgr.EnableTextures(true);
		m_connectionTexture->Apply();
		BasicDrawObjects::DrawTexturedLine(m_travelPoints[itravelPoint], m_travelPoints[itravelPoint + 1], 0.1f, Color4f());
		g_texturemgr.EnableTextures(false);
	}
}

void CGoPath::Init(CFollowState& o_followState) const
{
#if DEBUG
	if (m_travelPoints.size() < 2)
	{
		printf("Error: Supply line (%s) is too small to travel on! Needs at least two point", GetName());
		return;
	}
#endif 

	memset(&o_followState, 0, sizeof(o_followState));

	// get starting position
	o_followState.m_pos = m_travelPoints[0];
	o_followState.m_lastPos = o_followState.m_pos;
	o_followState.m_distTraveled = 0;
	o_followState.m_curSeg = 0;
}

bool CGoPath::Advance(CFollowState& io_followState, float i_distanceToTravel) const
{
	//if we are at the end of the line.. then leave and say we are done
	if (io_followState.m_distTraveled >= m_length)
	{
		return true;
	}
	
	int curSeg = io_followState.m_curSeg;
	float distanceRemaining = i_distanceToTravel;
	bool isAtEnd = false;
	Vector2f curPos = io_followState.GetPos();
	while(distanceRemaining > 0.0f)
	{
		//looking at the end point of this segement
		int iTravelingToPoint = curSeg + 1;
		
		//make sure we aren't at the end
		if (iTravelingToPoint != m_travelPoints.size())
		{
			Vector2f travelVector = m_travelPoints[iTravelingToPoint] - curPos;
			float distanceToNextPoint = travelVector.Length();
			
			//if need to go farther than this point can take us...
			// eat the distance and go to the next node
			if (m_distances[curSeg] <= io_followState.m_distTraveled)
			{
				//set the position at th end point
				curPos = m_travelPoints[iTravelingToPoint];
				curSeg++;
				distanceRemaining -= distanceToNextPoint;
			}
			else
			{
				//push the position in the direction of the end point
				travelVector.Normalize();
				curPos += (travelVector * distanceRemaining);
				distanceRemaining = 0.0f;
			}
		}
		else
		{
			isAtEnd = true;
		}
		
		
	}
	
	//update the follow state
	io_followState.m_curSeg = curSeg;
	io_followState.m_distTraveled += i_distanceToTravel - distanceRemaining;
	io_followState.m_lastPos = io_followState.m_pos;
	io_followState.m_pos = curPos;
	
	return isAtEnd;
}

/*-----------------------------------EOF!-----------------------------------*/ 
